#ifndef RESPSYS_H
#define RESPSYS_H
#include "Sensor.h"
#include "list.h" //*** we may need to implement list class

//////////////////////////////////////////////////////////////////////////
class ControlSys;  // it maybe another name! attention //***
//////////////////////////////////////////////////////////////////////////
class RespSys;
class AlarmSys;
class EmgcySys;
class MobilePhone;
class Internet_Communicate;
class phone_number;


//*** problem is here: the address of the homeowner is very important to the alarm system.
// At the same time, this information seems to put in the control system easy
class Location;
Location g_location;
//***


class ResSys
{
private:
	AlarmSys m_alarm;
	EmgcySys m_emergency;
	Msg m_msg;

public:
	ResSys(const Msg _msg) : m_msg(_msg) {}
	void Handle_Exception();
};

void ResSys::Handle_Exception()
{
	// determine the type of the exception
	// deal with it
	//*** to be continue...
}



class AlarmSys
{
	AlarmSys(
		const Msg _msg, 
		const list< phone_number > &_police_phone_number,
		const list< phone_number > &_owner_phone_number,
		const list< phone_number > &_principal_phone_number
	);

	void call_police( const Exception & _Exception ) const;
	void inform_owner_or_principal( const Exception & _Exception ) const;

private:
	MobilePhone m_phone;
	Internet_Communicate m_internet;
	list< phone_number > m_police_phone_number;
	list< phone_number > m_owner_phone_number;
	list< phone_number > m_principal_phone_number;
	Msg m_msg;
};

AlarmSys::AlarmSys( 
	const Msg _msg, 
	const list< phone_number > &_police_phone_number, 
	const list< phone_number > &_owner_phone_number, 
	const list< phone_number > &_principal_phone_number
	: 
    m_msg(_msg), 
    m_police_phone_number(_police_phone_number), 
    m_owner_phone_number(_owner_phone_number), 
	m_principal_phone_number(_principal_phone_number), 
	m_internet(_msg),
	m_phone(_msg)
{
}

void AlarmSys::call_police( const Exception & _Exception )
{
	int i;
	int count = m_police_phone_number.size();
	for ( i = 0; i < count; i++ )
	{
		MobilePhone.call(m_police_phone_number[i], _exception);
	}
}

void AlarmSys::inform_owner_or_principal( const Exception & _Exception ) const
{
	int i;
	int count = m_owner_phone_number.size();
	for ( i = 0; i < count; i++ )
	{
		MobilePhone.call(m_owner_phone_number[i], _Exception);
	}

 	count = m_principal_phone_number.size();
	for ( i = 0; i < count; i++ )
	{
		MobilePhone.call(m_principal_phone_number[i], _Exception);
	}
}



class MobilePhone
{
public:
	MobilePhone(const phone_number _phone_number) : m_phone_number(_phone_number) {}
	void call(const phone_number & _phone_number, const Exception &_Exception) const;

private:
	phone_number m_phone_number;
};


void MobilePhone::call(const phone_number & _phone_number, const Exception &_Exception) const
{
	cout << "From " << m_phone_number << endl;
	     << "Call " << _phone_number  << endl;
		 << "Exception :" << _Exception << endl;
}


// Note that the phone number have three parts:
// 1) international code
// 2) region code
// 3) normal code
class phone_number
{
public:
	phone_number() : m_international(0), m_region(0), m_normal(0) {};
	phone_number(int region, int region, int _normal) : m_international(region), m_region(region), m_normal(_normal) {};
	void  get(int &international, int &region, int &_normal) const;
	phone_number set_internationl( int _international ) { m_international = _international; }
	phone_number set_region( int _region ) { m_region = _region; }
	phone_number set_normal( int _normal ) { m_normal = _normal; }

private:
	int m_international;
	int m_region;
	int m_normal;
};

ostream &operator<<(ostream &sout, const phone_number & _phone_number)
{
	int international;
	int region;
	int _normal;
	_phone_number.get(international, region, _normal);
	sout << international << "-" << region << "-" << _normal;
	return sout;
}

void phone_number::get(int &international, int &region, int &_normal) const
{
	international = m_international;
	region = m_region;
	_normal = m_normal;
}


class Internet_Communicate
{
public:
	Internet_Communicate(const phone_number _phone_number) :  m_phone_number(_phone_number) {}
	void inform_owner_or_principal(const phone_number & _phone_number, const Exception &_Exception) const;

private:
	phone_number m_phone_number;
};

void Internet_Communicate::inform_owner_or_principal(const phone_number & _phone_number, const Exception &_Exception) const
{
	cout << "From " << m_phone_number << endl;
	<< "Call " << _phone_number  << endl;
	<< "Exception :" << _Exception << endl;
}

class EmgcySys
{
public:
	EmgcySys();
	inline void turn_off_water() const { is_water_open = false; }
	inline void turn_on_water() const  { is_water_open = true;  }
	inline void turn_off_power() const { is_power_open = false; }
	inline void turn_on_power() const  { is_power_open = true;  }

private:
	bool is_water_open;
	bool is_power_open;
};


#endif /*RESPSYS_H*/
